package study;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 学习的切面
 * 是特殊的类，并是Spring的配置。
 * 使用注解定义切面
 */
@Aspect
@Component
public class StudyAspect {

    //如果切点是一样的，可以将切点抽出来

    @Pointcut("execution(* study.Study.readbook()) ")
//    @Pointcut("execution(** study.Study.readbook(..)) ")//为所有的名称为readbook的方法作为切点
    public void readbook(){};
    /**
     * 看书之前，调整心态
     *
     */
    @Before("readbook()")// 定义切点
    public void AdjustMentality(){
        System.out.println("调整心态");
    }

    /**
     * 看书之后，关灯睡觉
     */
    @After("execution(* study.Study.readbook())")//既可以用定义好的切点，也可以自己写切点
    public void lightOff(){
        System.out.println("关灯，睡觉");
    }

    /**
     * 使用环绕通知。
     * 如果同一个切点，既用了before注解，又用了环绕通知，那么程序会如何执行。
     * 优先执行环绕通知，只有环绕通知调用了 切入点的方法，加before注解的方法才会调用。
     */
    @Around("readbook()")
    public void aroundRead(ProceedingJoinPoint joinPoint){
        try{
            System.out.println("检查看了什么书");
            Object proceed = joinPoint.proceed();
            System.out.println("我是方法的返回值类型"+(proceed!=null?proceed.getClass().getName():"null"));
            System.out.println("看完书了！");
        }catch (Throwable throwable) {
            throwable.getMessage();
            System.out.println("报错了");
        }
    }
    /**
     * 指定参数的切点
     */
    @Pointcut("execution(* study.Study.readbook(String))&&args(title)) ")//为所有的名称为readbook的方法作为切点
    public void readTitleBook(String title){};

    @Before("readTitleBook(title)")
    public void beforeReadTitleBook(String title){
        System.out.println("我读了："+title);
    }
}
